﻿
using System;

namespace PBRSystem.Coord
{
    public class PBRPoint2
    {
        #region Variables
        private float _x, _y;
        #endregion

        #region Contructor

        public PBRPoint2()
        {
            _x = _y = 0;
        }

        public PBRPoint2(float x, float y)
        {
            _x = x;
            _y = y;
        }

        public PBRPoint2(PBRPoint2 point)
        {
            _x = point.X;
            _y = point.Y;
        }
        #endregion

        #region Reporter
        public float X
        {
            set
            {
                _x = value;
            }
            get
            {
                return _x;
            }
        }
        
        public float Y
        {
            set
            {
                _y = value;
            }
            get
            {
                return _y;
            }
        }


        #endregion

        #region Operator
        public static PBRPoint2 operator +(PBRPoint2 a, PBRPoint2 b)
        {
            return new PBRPoint2(a.X + b.X, a.Y + b.Y);
        }

        public static PBRPoint2 operator +(PBRPoint2 a, PBRVector2 b)
        {
            return new PBRPoint2(a.X + b.X, a.Y + b.Y);
        }

        public static PBRVector2 operator -(PBRPoint2 a, PBRPoint2 b)
        {
            return new PBRVector2(a.X - b.X, a.Y - b.Y);
        }

        public static PBRPoint2 operator -(PBRVector2 a, PBRPoint2 b)
        {
            return new PBRPoint2(a.X - b.X, a.Y - b.Y);
        }

        public static PBRPoint2 operator *(PBRPoint2 a, float s)
        {
            return new PBRPoint2(a.X * s, a.Y * s);
        }

        public static PBRPoint2 operator /(PBRPoint2 a, float s)
        {
            if(s == 0)
            {
                return a;
            }

            return new PBRPoint2(a.X / s, a.Y / s);
        }

        public static PBRPoint2 operator /(PBRPoint2 a, PBRPoint2 b)
        {
            if (b.X == 0 || b.Y == 0)
            {
                return a;
            }

            return new PBRPoint2(a.X / b.X, a.Y / b.Y);
        }

        public static bool operator ==(PBRPoint2 a, PBRPoint2 b)
        {
            return (a.X == b.X) && (b.Y == a.Y);
        }

        public static bool operator !=(PBRPoint2 a, PBRPoint2 b)
        {
            return (a.X != b.X) || (b.Y != a.Y);
        }



        #endregion

        #region Override
        public override bool Equals(object obj)
        {
            if(!(obj is PBRPoint2))
            {
                return false;
            }

            PBRPoint2 p = (PBRPoint2)obj;
            return (_x == p.X)&&(_y == p.Y);

        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        #endregion

        #region Operation
        public PBRPoint2 Min(PBRPoint2 p1, PBRPoint2 p2)
        {
            return new PBRPoint2(Math.Min(p1.X, p2.X), Math.Min(p1.Y, p2.Y));
        }

        public PBRPoint2 Max(PBRPoint2 p1, PBRPoint2 p2)
        {
            return new PBRPoint2(Math.Max(p1.X, p2.X), Math.Max(p1.Y, p2.Y));
        }

        public PBRPoint2 Floor(PBRPoint2 p)
        {
            return new PBRPoint2((float)Math.Floor(p.X), (float)Math.Floor(p.Y));
        }

        public PBRPoint2 Ceil(PBRPoint2 p)
        {
            return new PBRPoint2((float)Math.Ceiling(p.X), (float)Math.Ceiling(p.Y));
        }

        public PBRPoint2 Abs(PBRPoint2 p)
        {
            return new PBRPoint2((float)Math.Abs(p.X), (float)Math.Abs(p.Y));
        }

        public static float Distance(PBRPoint2 p1, PBRPoint2 p2)
        {
            return (p1 - p2).Length();
        }

        public static float DistanceSquared(PBRPoint2 p1, PBRPoint2 p2)
        {
            return (p1 - p2).LengthSquare();
        }

        public static PBRPoint2 Lerp(float t, PBRPoint2 p0, PBRPoint2 p1)
        {
            return p0 * (1 - t) + p1 * t;
        } 

        #endregion
    }
}
    
